package com.wizo.csb;

import java.io.InputStream;
import java.util.Properties;

/**
 * A layer for accessing a cloud storage to benchmarked. Each thread in the client
 * will be given its own instance of whatever storage class is to be used in the test.
 * This class should be constructed using a no-argument constructor, so we can load it
 * dynamically. Any argument-based initialization should be done by init().
 * 
 * The semantics of methods such as upload and download vary from storage to storage.
 * In particular, operations may or may not be durable once these methods commit.
 */
public abstract class Storage {

	/**
	 * Properties for configuring this storage.
	 */
	Properties _p = new Properties();
	/**
	 * Set the properties for this storage.
	 */
	public void setProperties(Properties p){
		_p = p;
	}
	/**
	 * Get the properties for the storage
	 */
	public Properties getProperties(){
		return _p;
	}
	
	/**
	 * Initialize any state for this storage
	 * Called once per storage instance; there is one storage instance per client thread.
	 */
	public void init() throws StorageException{
		
	}
	
	/**
	 * Cleanup any state for this storage.
	 * Called once per storage instance; there is one storage instance per client thread.
	 */
	public void cleanup() throws StorageException{
		
	}
	
	/**
	 * Download an object from the container.
	 * 
	 * @param container The name of the bucket.
	 * @param name The object name of the object to downlaod.
	 * @return inputStream The inputStream of the object content. If null that means the object does't 
	 * exist or something bad happened.
	 */
	public abstract InputStream download(String container, String name);
	
	/**
	 * Upload an object from the container.
	 * 
	 * @param container The name of the bucket.
	 * @param name The object name of the object to upload.
	 * @param inputStream The inputStream of the object content to upload.
	 * @param contentLength The length of the object content.
	 * @param contentType The type of the object content.
	 * @return Zero on success, a non-zero error code on error.
	 */
	public abstract int upload(String container, String name, InputStream inputStream, 
			long contentLength, String contentType);
	
	/**
	 * Delete an object for good from container.
	 * 
	 * @param bucket The name of the container.
	 * @param name The object name of the object to delete.
	 * @return Zero on success, a non-zero error code in error or "not found".
	 */
	public abstract int delete(String container, String name);
	
	/**
	 * Copy an objectS from containerS to containerD and rename it objectD. 
	 * Replace the metadata depand on the value of replaceMetadata
	 * 
	 *  @param containerS The source bucket.
	 *  @param objectS The source object.
	 *  @param containerD The destination bucket.
	 *  @param objectD The destination object.
	 *  @param replaceData Ture if you want to replace metadata, otherwise you don't.
	 *  @return Zero on success, a non-zero error code on error or "not found".
	 */
	public abstract int copy(String containerS, String objectS, String containerD, String objectD, 
			boolean replaceMetadata);
	
	/**
	 * Move an objectS from containerS to containerD and rename it objectD, 
	 * and objectS in bucketS will not exist any more. 
	 * Replace the metadata depand on the value of replaceMetadata.
	 * 
	 *  @param containerS The source bucket.
	 *  @param objectS The source object.
	 *  @param containerD The destination bucket.
	 *  @param objectD The destination object.
	 *  @param replaceData Ture if you want to replace metadata, otherwise you don't.
	 *  @return Zero on success, a non-zero error code on error or "not found".
	 */
	public abstract int move(String containerS, String objectS, String containerD, String objectD, 
			boolean replaceMetadata);
	
}